package relu.R.landscape;
import relu.R.weeds.*;
import jfm.model.StubblesComponent;
import jfm.model.Types.CropType;
import jfm.model.RotationMatrix;
import java.util.*;
import jfm.utils.*;
import relu.R.birds.*;

public class Field {
	private LSFarm owningFarm=null;
	private List<Bird> birdsInRange=new ArrayList<Bird>();
	private CropType prevCrop=null;
	private CropType curCrop=null;
	public final double xPos;
	public final double yPos;
	private final double boxLength;
	private final double fieldArea;
	public String cropTransition(){
		return prevCrop+" to "+curCrop+ " "+isStubble();
	}
	
//	private Set<CropTransition> doneTransitions=new HashSet<CropTransition>();
//	private Set<CropTransition> noInfoTransitions=new HashSet<CropTransition>();
	
//	private final Map<WeedSpecies,DensityVector> weeds=new HashMap<WeedSpecies,DensityVector>();
	
	// Integers representing the density categories for weeds in this field 
	private final Map<WeedSpecies,Integer> weeds=new HashMap<WeedSpecies,Integer>();
	public Field(double x,double y,double boxl,double area){
		xPos=x;
		yPos=y;
		boxLength=boxl;
		fieldArea=area;
	}

	// Returns the number of seeds per hectare in stubble from this species
	public double getDensity(WeedSpecies sp){
		if ( weeds.containsKey(sp)){
			// This gets number of plants per square meter
			double plantsperSquareM= sp.bins()[weeds.get(sp)];
			// Weed need to return number of seeds per hectare
			return 10000*plantsperSquareM*sp.stubbleSeedsPerPlant();
			
		} else {
			return 0;
		}
	}
	
	
	/** Check whether this field will be stubble during the food critical time period */
	public boolean isStubble(){
		double pstubble=owningFarm.stubbleProbability(prevCrop, curCrop);
		double rnorm=Landscape.rGen.nextDouble();
		if ( rnorm < pstubble){
			return true;
		} else {
			return false;
		}
	}
	
	/** Returns the share of weed seed food available 
	 * to a single bird for a particular weed species */
	public double getShare(WeedSpecies sp){
		if (isStubble()){
			return getDensity(sp)/birdsInRange.size();
		} else {
			return 0;
		}
	}
	
	public double area(){
		return fieldArea;
	}
	
	public void assignToNewBirdsInRange(List<Bird> birds){
		for( Bird bd:birds){
			if ( bd.inRange(xPos,yPos,boxLength)){
				birdsInRange.add(bd);
				bd.addField(this);
			}
		}
	}
	
	public void assignToAllBirdsInRange(List<Bird> birds){
		birdsInRange.clear();
		assignToNewBirdsInRange(birds);
	}
	

	
	public void assignToFarm(LSFarm theFarm){
		owningFarm=theFarm;
		owningFarm.addField(this);
	}
	
	public void assignToNearestFarm(SpatialLandscape parent){
		/*
		int nearest=-1;
		double closestD=100000000.0;// Really far away
		for(int i=0;i<farms.size();i++){
			double dist=Landscape.farmFieldDistance(farms.get(i),this);
			if ( dist < closestD){
				nearest=i;
				closestD=dist;
			}
		}*/
		assignToFarm(parent.owningFarm(this.xPos, this.yPos));
	}
	
	public void addWeedPopulation(WeedSpecies sp,double[] initialDensities){
		double rand=SpatialLandscape.rGen.nextDouble();
		weeds.put(sp,JFMMath.chooseWeightedRandom(initialDensities,rand));
	}
	
	
	
	public void rotateCropsAndPropagateWeeds() throws NullPointException {
		RotationMatrix rm=owningFarm.getRotationMatrix();
		if ( curCrop==null){
			curCrop=rm.pickNewCrop(null, SpatialLandscape.rGen.nextDouble());
		}
		prevCrop=curCrop;
		curCrop=rm.pickNewCrop(curCrop,SpatialLandscape.rGen.nextDouble());
//		System.out.println("About to create ct "+prevCrop+" "+curCrop);
//		CropTransition thisTrans=new CropTransition(prevCrop,curCrop);
//		CropTransition thisTrans=new CropTransition();
//		System.out.println(thisTrans);
		for(WeedSpecies sp:weeds.keySet()){
			TransitionMatrix spTM=owningFarm.parentLandscape.getTransitionMatrix(sp,prevCrop,curCrop);
		//	System.out.println("Got tm for "+sp+" "+spTM);
			if ( spTM != null){
	//			if ( !doneTransitions.contains(thisTrans)){
	//				doneTransitions.add(thisTrans);
		//			System.out.println("New Transition "+prevCrop+" "+curCrop);
	//			}
		//		System.out.println("Doing transition");
				weeds.put(sp, TransitionMatrix.doTransition(spTM, weeds.get(sp)));
			} else {
				System.err.println("No info for "+prevCrop+" "+curCrop);
				System.exit(1);
//				if ( !noInfoTransitions.contains(thisTrans)){
//					noInfoTransitions.add(thisTrans);
//				}
				// Do nothing ... no information available on this transition.
			}
		}
	}
	
}
